package xyz.shenmegui.foodcheckserver.controller;

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import xyz.shenmegui.foodcheckserver.DO.*;
import xyz.shenmegui.foodcheckserver.DO.Collection;
import xyz.shenmegui.foodcheckserver.annotation.Login;
import xyz.shenmegui.foodcheckserver.annotation.LoginUser;
import xyz.shenmegui.foodcheckserver.http.HttpResponse;
import xyz.shenmegui.foodcheckserver.service.*;
import xyz.shenmegui.foodcheckserver.utils.ChatUtils;
import xyz.shenmegui.foodcheckserver.utils.PythonUtil;
import xyz.shenmegui.foodcheckserver.utils.StringUtils;

import java.time.LocalDate;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@RestController
@RequestMapping("/recommend")
public class RecommendController {

    @Autowired
    private PythonUtil pythonUtil;

    @Autowired
    private MenuService menuService;

    @Autowired
    private CollectionService collectionService;

    @Autowired
    private DailyRecommendService dailyRecommendService;

    private static final int[] seedList = new int[]{1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997};

    /**
     * Login 注解，确保用户登录
     * @param user 通过 LoginUser 注解获取登陆的用户信息
     * @param date
     * @return
     */
    @Login
    @PostMapping("/dailyRecommend")
    public HttpResponse getDailyRecommend(@LoginUser User user,@RequestBody Map<String, String> date) {
        // 获取现在日期
        LocalDate inDate = LocalDate.now();
        // 如果前端出传入数据不为空，则获取前端传入的日期
        if (StringUtils.isNotEmpty(date)) {
            inDate = LocalDate.parse(date.get("date"));
        }
        // 从数据库中获取对应日期、对应用户的推荐食谱
        List<Menu> menus = dailyRecommendService.getRecommend(user.getId(), inDate);
        if (menus.isEmpty()) {
            // 通过用户健康信息，生成对应条件
            String keyword = user.buildCondition();
            // 数据库中有，则返回，没有则执行食谱生成
            ChatUtils chatUtils = new ChatUtils();
            // 通过科大讯飞认知大模型生成食谱
            String result = chatUtils.chat(keyword);
            // 处理生成食谱，构造食谱对象
            List<Menu> menuList = buildMenus(result);
            // 如果构造的食谱不为空，则存放至数据库中
            if (!menuList.isEmpty()) {
                // 插入数据库食谱表中
                menuService.insertMenus(menuList);
                menus.addAll(menuList);
                Menu menu = menuList.get(0);
                int seed = seedList[new Random().nextInt(10)];
                if (menu != null) {
                    DailyRecommend dailyRecommend = new DailyRecommend();
                    dailyRecommend.setDate(inDate);
                    dailyRecommend.setUid(user.getId());
                    dailyRecommend.setSeedId(seed);
                    // 插入数据库每日推荐表中
                    dailyRecommendService.insertRecommend(dailyRecommend);
                }
                List<Menu> menuBySeedId = menuService.getMenuBySeedId(seed);
                menus.clear();
                menus.addAll(menuBySeedId);
            }
        }
        // 返回推荐食谱数据
        return HttpResponse.okWithData(menus);
    }

    /**
     * 使用正则表达式对返回结果进行解析，构造系统需要的食谱
     * @param content
     * @return
     */
    private List<Menu> buildMenus(String content) {

        // 对象声明与初始化
        ArrayList<Menu> menus = new ArrayList<>();

        // 为每日菜谱生成随机种子，保证不同天的菜谱是不同的种子，即确保每天菜谱不一样
        int id = getRandomId();
        // 从库中查询改 seed，如果存在则重新生成
        List<Menu> menuBySeedId = menuService.getMenuBySeedId(id);
        while (!CollectionUtils.isEmpty(menuBySeedId)) {
            id = getRandomId();
            menuBySeedId = menuService.getMenuBySeedId(id);
        }
        // 整理字符串，去除替换字符
        content = content.replaceAll("\n", "").replaceAll("：", ":").replaceAll(" ", "");

        // 早餐部分提取正则表达式
        String breakfastReg = "早[餐饭](?:：|\\:)(.*?)(?=[午中]|[餐饭])";
        String lunchReg = "[午中][餐饭]:(.*?)(?=晚[餐饭])";
        String dinnerReg = "晚[餐饭]:(.*?)$";

        // 食材部分提取正则表达式
        String foodsReg = "食材:(.*?)。";
        // 做法部分提取正则表达式
        String preparationReg = "做法:(.*?)。";
        // 能量部分提取正则表达式
        String energyReg = "能量:(.*?)。";

        // 模板预编译
        Pattern breakfastPattern = Pattern.compile(breakfastReg);
        // 字符匹配
        Matcher breakfastMatcher = breakfastPattern.matcher(content);
        Pattern lunchPattern = Pattern.compile(lunchReg);
        Matcher lunchMatcher = lunchPattern.matcher(content);
        Pattern dinnerPattern = Pattern.compile(dinnerReg);
        Matcher dinnerMatcher = dinnerPattern.matcher(content);

        // 模板预编译
        Pattern foodsPattern = Pattern.compile(foodsReg);
        // 模板预编译
        Pattern preparationPattern = Pattern.compile(preparationReg);
        // 模板预编译
        Pattern energyPattern = Pattern.compile(energyReg);

        // 早餐，如果正则匹配上则进一步提取早餐的食材、做法、能量
        while (breakfastMatcher.find()) {
            System.out.println("---- breakfast: " + breakfastMatcher.group(1)); // 输出匹配到的单词
            // 获取到的字符串
            String breakfastContent = breakfastMatcher.group(1);
            if (StringUtils.isNotEmpty(breakfastContent)) {
                // 提取食材部分
                Matcher foodsMatcher = foodsPattern.matcher(breakfastContent);
                Menu menu = new Menu();
                menu.setType("1");
                menu.setSeed(id);
                // 食材
                while (foodsMatcher.find()) {
                    System.out.println("foods: " + foodsMatcher.group(1)); // 输出匹配到的单词
                    String foodsContent = foodsMatcher.group(1);
                    // 设置随机种子
                    menu.setFoods(foodsContent);
                }
                // 提取做法部分
                Matcher preparationMatcher = preparationPattern.matcher(breakfastContent);
                while (preparationMatcher.find()) {
                    System.out.println("preparation: " + preparationMatcher.group(1)); // 输出匹配到的单词
                    String preparationContent = preparationMatcher.group(1);
                    menu.setPreparation(preparationContent);
                }
                // 提取能量部分
                Matcher energyMather = energyPattern.matcher(breakfastContent);
                while (energyMather.find()) {
                    System.out.println("energy: " + energyMather.group(1)); // 输出匹配到的单词
                    String energyContent = energyMather.group(1);
                    menu.setEnergy(energyContent);
                }
                // 将早餐加入到每日菜谱中，午餐、晚餐同理
                menus.add(menu);
            }
        }

        // 午餐
        while (lunchMatcher.find()) {
            System.out.println("---- lunch: " + lunchMatcher.group(1)); // 输出匹配到的单词
            String lunchContent = lunchMatcher.group(1);
            if (StringUtils.isNotEmpty(lunchContent)) {
                Matcher foodsMatcher = foodsPattern.matcher(lunchContent);
                Menu menu = new Menu();
                menu.setType("2");
                menu.setSeed(id);
                while (foodsMatcher.find()) {
                    System.out.println("foods: " + foodsMatcher.group(1)); // 输出匹配到的单词
                    String foodsContent = foodsMatcher.group(1);
                    menu.setFoods(foodsContent);
                }
                Matcher preparationMatcher = preparationPattern.matcher(lunchContent);
                while (preparationMatcher.find()) {
                    System.out.println("preparation: " + preparationMatcher.group(1)); // 输出匹配到的单词
                    String preparationContent = preparationMatcher.group(1);
                    menu.setPreparation(preparationContent);
                }
                Matcher energyMather = energyPattern.matcher(lunchContent);
                while (energyMather.find()) {
                    System.out.println("energy: " + energyMather.group(1)); // 输出匹配到的单词
                    String energyContent = energyMather.group(1);
                    menu.setEnergy(energyContent);
                }
                menus.add(menu);
            }
        }

        // 晚餐
        while (dinnerMatcher.find()) {
            System.out.println("---- dinner: " + dinnerMatcher.group(1)); // 输出匹配到的单词
            String dinnerContent = dinnerMatcher.group(1);
            if (StringUtils.isNotEmpty(dinnerContent)) {
                Matcher foodsMatcher = foodsPattern.matcher(dinnerContent);
                Menu menu = new Menu();
                menu.setType("3");
                menu.setSeed(id);
                while (foodsMatcher.find()) {
                    System.out.println("foods: " + foodsMatcher.group(1)); // 输出匹配到的单词
                    String foodsContent = foodsMatcher.group(1);
                    menu.setFoods(foodsContent);
                }
                Matcher preparationMatcher = preparationPattern.matcher(dinnerContent);
                while (preparationMatcher.find()) {
                    System.out.println("preparation: " + preparationMatcher.group(1)); // 输出匹配到的单词
                    String preparationContent = preparationMatcher.group(1);
                    menu.setPreparation(preparationContent);
                }
                Matcher energyMather = energyPattern.matcher(dinnerContent);
                while (energyMather.find()) {
                    System.out.println("energy: " + energyMather.group(1)); // 输出匹配到的单词
                    String energyContent = energyMather.group(1);
                    menu.setEnergy(energyContent);
                }
                menus.add(menu);
            }
        }
        // 返回结果
        return menus;
    }

    private int getRandomId() {
        Random random = new Random();
        int id = random.nextInt();
        return Math.abs(id / 10000000);
    }
}
